home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus 1999 #2 / Amiga Plus CD - 1999 - No. 2.iso / System-Boost / Workbench / ToolManager / Source / Prefs / base.c < prev    next >
C/C++ Source or Header  |  1998-06-17  |  15KB  |  555 lines

  1. /*
  2.  * base.c  V3.1
  3.  *
  4.  * Base class for TM objects
  5.  *
  6.  * Copyright (C) 1990-98 Stefan Becker
  7.  *
  8.  * This source code is for educational purposes only. You may study it
  9.  * and copy ideas or algorithms from it for your own projects. It is
  10.  * not allowed to use any of the source codes (in full or in parts)
  11.  * in other programs. Especially it is not allowed to create variants
  12.  * of ToolManager or ToolManager-like programs from this source code.
  13.  *
  14.  */
  15.  
  16. #include "toolmanager.h"
  17.  
  18. /* Local data */
  19. static const char *TextName;
  20. static const char *HelpName;
  21.  
  22. /* Base class instance data */
  23. struct BaseClassData {
  24.  struct MinList  bcd_AttachList;
  25.  char           *bcd_Name;
  26.  ULONG           bcd_ID;
  27.  ULONG           bcd_Type;
  28.  Object         *bcd_List;
  29.  Object         *bcd_Root;
  30.  Object         *bcd_Active;
  31.  Object         *bcd_String;
  32.  Object         *bcd_Child;
  33.  Object         *bcd_Buttons;
  34. };
  35. #define TYPED_INST_DATA(cl, o) ((struct BaseClassData *) INST_DATA((cl), (o)))
  36.  
  37. /* Base class method: OM_NEW */
  38. #undef  DEBUGFUNCTION
  39. #define DEBUGFUNCTION BaseClassNew
  40. static ULONG BaseClassNew(Class *cl, Object *obj, struct opSet *ops)
  41. {
  42.  Object     *rc   = NULL;
  43.  const char *name;
  44.  
  45.  BASE_LOG((LOG1(Tags, "0x%08lx", ops->ops_AttrList),
  46.            PrintTagList(ops->ops_AttrList)))
  47.  
  48.  /* Duplicate name */
  49.  if (name = DuplicateString((const char *)
  50.                              GetTagData(TMA_Name, NULL, ops->ops_AttrList))) {
  51.   Object *Root;
  52.  
  53.   BASE_LOG(LOG2(Name, "%s (0x%08lx)", name, name))
  54.  
  55.   /* Create object */
  56.   if (rc = (Object *) DoSuperNew(cl, obj,
  57.                                    MUIA_Window_AppWindow, TRUE,
  58.                                    WindowContents,        Root = VGroup,
  59.                                    End,
  60.                                    TAG_MORE,              ops->ops_AttrList)) {
  61.    struct BaseClassData *bcd = TYPED_INST_DATA(cl, rc);
  62.  
  63.    BASE_LOG(LOG1(Root, "0x%08lx", Root))
  64.  
  65.    /* Initialize attach list */
  66.    NewList((struct List *) &bcd->bcd_AttachList);
  67.  
  68.    /* Initialize instance data */
  69.    bcd->bcd_Name    = name;
  70.    bcd->bcd_ID      = 0;
  71.    bcd->bcd_Type    = GetTagData(TMA_Type, 0, ops->ops_AttrList);
  72.    bcd->bcd_List    = (Object *) GetTagData(TMA_List, NULL, ops->ops_AttrList);
  73.    bcd->bcd_Root    = Root;
  74.    bcd->bcd_Active  = NULL;
  75.  
  76.    /* Window action */
  77.    DoMethod(rc, MUIM_Notify, MUIA_Window_CloseRequest, TRUE,
  78.             bcd->bcd_List, 3, TMM_Update, rc, TMV_Finish_Cancel);
  79.  
  80.    /* AppWindow action */
  81.    DoMethod(rc, MUIM_Notify, MUIA_AppMessage, MUIV_EveryTime,
  82.             rc, 3, MUIM_CallHook, &AppMessageHook, MUIV_TriggerValue);
  83.  
  84.   } else
  85.  
  86.    /* Couldn't create object, free name */
  87.    FreeVector(name);
  88.  }
  89.  
  90.  BASE_LOG(LOG1(Result, "0x%08lx", rc))
  91.  
  92.  /* Return pointer to created object */
  93.  return((ULONG) rc);
  94. }
  95.  
  96. /* Base class method: OM_DISPOSE */
  97. #undef  DEBUGFUNCTION
  98. #define DEBUGFUNCTION BaseClassDispose
  99. static ULONG BaseClassDispose(Class *cl, Object *obj, Msg msg)
  100. {
  101.  struct BaseClassData *bcd = TYPED_INST_DATA(cl, obj);
  102.  
  103.  BASE_LOG(LOG1(Disposing, "0x%08lx", obj))
  104.  
  105.  /* Close edit window first */
  106.  DoMethod(obj, TMM_Finish, TMV_Finish_Cancel);
  107.  
  108.  /* Notify all attached objects */
  109.  {
  110.   struct AttachData *ad;
  111.  
  112.   /* For each attached object */
  113.   while (ad = (struct AttachData *)
  114.                RemHead((struct List *) &bcd->bcd_AttachList)) {
  115.  
  116.    BASE_LOG(LOG1(Notify, "0x%08lx", ad->ad_AttachedTo))
  117.  
  118.    /* Clear object pointer -> object is going to be disposed */
  119.    ad->ad_Object = NULL;
  120.  
  121.    /* Send notification */
  122.    DoMethod(ad->ad_AttachedTo, TMM_Notify, ad);
  123.  
  124.    /* Free attach data */
  125.    FreeMemory(ad, sizeof(struct AttachData));
  126.   }
  127.  }
  128.  
  129.  /* Free name */
  130.  FreeVector(bcd->bcd_Name);
  131.  
  132.  /* Call SuperClass */
  133.  return(DoSuperMethodA(cl, obj, msg));
  134. }
  135.  
  136. /* Base class method: OM_SET */
  137. #undef  DEBUGFUNCTION
  138. #define DEBUGFUNCTION BaseClassSet
  139. static ULONG BaseClassSet(Class *cl, Object *obj, struct opSet *ops)
  140. {
  141.  struct TagItem *tstate = ops->ops_AttrList;
  142.  struct TagItem *ti;
  143.  
  144.  BASE_LOG((LOG1(Tags, "0x%08lx", ops->ops_AttrList),
  145.                 PrintTagList(ops->ops_AttrList)))
  146.  
  147.  /* Scan tag list */
  148.  while (ti = NextTagItem(&tstate))
  149.  
  150.   /* Which attribute shall be set? */
  151.   switch (ti->ti_Tag) {
  152.    case TMA_ID:
  153.     TYPED_INST_DATA(cl, obj)->bcd_ID = ti->ti_Data;
  154.     break;
  155.  
  156.    case TMA_Name: {
  157.      char *newname;
  158.  
  159.      BASE_LOG(LOG2(Name, "%s (0x%08lx)", ti->ti_Data, ti->ti_Data))
  160.      /* Duplicate new name */
  161.      if (newname = DuplicateString((const char *) ti->ti_Data)) {
  162.       struct BaseClassData *bcd = TYPED_INST_DATA(cl, obj);
  163.       struct AttachData    *ad  = (struct AttachData *)
  164.                                    GetHead(&bcd->bcd_AttachList);
  165.  
  166.       BASE_LOG(LOG2(New Name, "%s (0x%08lx)", newname, newname))
  167.  
  168.       /* Free old name */
  169.       FreeVector(bcd->bcd_Name);
  170.  
  171.       /* Set new name */
  172.       bcd->bcd_Name = newname;
  173.  
  174.       /* Notify all attached objects */
  175.       while (ad) {
  176.  
  177.        BASE_LOG(LOG1(Notify, "0x%08lx", ad->ad_AttachedTo))
  178.  
  179.        /* Send notification */
  180.        DoMethod(ad->ad_AttachedTo, TMM_Notify, ad);
  181.  
  182.        /* Next object */
  183.        ad = (struct AttachData *) GetSucc((struct MinNode *) ad);
  184.       }
  185.      }
  186.     }
  187.     break;
  188.   }
  189.  
  190.  /* Call SuperClass */
  191.  return(DoSuperMethodA(cl, obj, (Msg) ops));
  192. }
  193.  
  194. /* Base class method: OM_GET */
  195. #undef  DEBUGFUNCTION
  196. #define DEBUGFUNCTION BaseClassGet
  197. static ULONG BaseClassGet(Class *cl, Object *obj, struct opGet *opg)
  198. {
  199.  ULONG rc;
  200.  
  201.  BASE_LOG(LOG2(Attribute, "0x%08lx (%s)", opg->opg_AttrID,
  202.                GetTagName(opg->opg_AttrID)))
  203.  
  204.  /* Which attribute is requested? */
  205.  switch(opg->opg_AttrID) {
  206.   case TMA_Name:
  207.    *opg->opg_Storage = (ULONG) TYPED_INST_DATA(cl, obj)->bcd_Name;
  208.  
  209.    /* Return TRUE to indicate that the attribute is implemented */
  210.    rc = TRUE;
  211.    break;
  212.  
  213.   case TMA_ID:
  214.    *opg->opg_Storage = TYPED_INST_DATA(cl, obj)->bcd_ID;
  215.  
  216.    /* Return TRUE to indicate that the attribute is implemented */
  217.    rc = TRUE;
  218.    break;
  219.  
  220.   case TMA_Type:
  221.    *opg->opg_Storage = TYPED_INST_DATA(cl, obj)->bcd_Type;
  222.  
  223.    /* Return TRUE to indicate that the attribute is implemented */
  224.    rc = TRUE;
  225.    break;
  226.  
  227.   default:
  228.    rc = DoSuperMethodA(cl, obj, (Msg) opg);
  229.    break;
  230.  }
  231.  
  232.  BASE_LOG(LOG2(Result, "%ld value 0x%08lx", rc, *opg->opg_Storage))
  233.  
  234.  return(rc);
  235. }
  236.  
  237. /* Base class method: TMM_Finish */
  238. #undef  DEBUGFUNCTION
  239. #define DEBUGFUNCTION BaseClassFinish
  240. static ULONG BaseClassFinish(Class *cl, Object *obj, struct TMP_Finish *tmpf)
  241. {
  242.  struct BaseClassData *bcd = TYPED_INST_DATA(cl, obj);
  243.  
  244.  BASE_LOG(LOG1(Type, "%ld", tmpf->tmpf_Type))
  245.  
  246.  /* MUI objects allocated? */
  247.  if (bcd->bcd_Active) {
  248.  
  249.   BASE_LOG(LOG0(Closing Window))
  250.  
  251.   /* Yes, close window */
  252.   set(obj, MUIA_Window_Open, FALSE);
  253.  
  254.   /* Use or Cancel? */
  255.   if (tmpf->tmpf_Type == TMV_Finish_Use) {
  256.    char *name;
  257.  
  258.    /* Get new name */
  259.    GetAttr(MUIA_String_Contents, bcd->bcd_String, (ULONG *) &name);
  260.  
  261.    /* Set new name */
  262.    SetAttrs(obj, TMA_Name, name, TAG_DONE);
  263.   }
  264.  
  265.   /* Remove object from application */
  266.   DoMethod(_app(obj),     OM_REMMEMBER, obj);
  267.  
  268.   /* Remove objects from root group */
  269.   DoMethod(bcd->bcd_Root, OM_REMMEMBER, bcd->bcd_Buttons);
  270.   if (bcd->bcd_Child) DoMethod(bcd->bcd_Root, OM_REMMEMBER, bcd->bcd_Child);
  271.   DoMethod(bcd->bcd_Root, OM_REMMEMBER, bcd->bcd_Active);
  272.  
  273.   /* Delete objects */
  274.   MUI_DisposeObject(bcd->bcd_Buttons);
  275.   MUI_DisposeObject(bcd->bcd_Active);
  276.   if (bcd->bcd_Child) MUI_DisposeObject(bcd->bcd_Child);
  277.  
  278.   /* Reset active flag */
  279.   bcd->bcd_Active = NULL;
  280.  }
  281.  
  282.  /* Return 1 to indicate that the method is implemented */
  283.  return(1);
  284. }
  285.  
  286. /* Base class method: TMM_Attach */
  287. #undef  DEBUGFUNCTION
  288. #define DEBUGFUNCTION BaseClassAttach
  289. static ULONG BaseClassAttach(Class *cl, Object *obj, struct TMP_Attach *tmpa)
  290. {
  291.  struct AttachData *rc;
  292.  
  293.  BASE_LOG(LOG1(Object, "0x%08lx", tmpa->tmpa_Object))
  294.  
  295.  /* Allocate memory for attach data */
  296.  if (rc = GetMemory(sizeof(struct AttachData))) {
  297.  
  298.   BASE_LOG(LOG1(Attach Data, "0x%08lx", rc))
  299.  
  300.   /* Initialize attach data */
  301.   rc->ad_Object     = obj;
  302.   rc->ad_AttachedTo = tmpa->tmpa_Object;
  303.  
  304.   /* Append attach data to list */
  305.   AddTail((struct List *) &TYPED_INST_DATA(cl, obj)->bcd_AttachList,
  306.           (struct Node *) rc);
  307.  }
  308.  
  309.  BASE_LOG(LOG1(Result, "0x%08lx", rc))
  310.  
  311.  return(rc);
  312. }
  313.  
  314. /* Base class method: TMM_Detach */
  315. #undef  DEBUGFUNCTION
  316. #define DEBUGFUNCTION BaseClassDetach
  317. static ULONG BaseClassDetach(Class *cl, Object *obj, struct TMP_Detach *tmpd)
  318. {
  319.  BASE_LOG(LOG1(Data, "0x%08lx", tmpd->tmpd_Data))
  320.  
  321.  /* Remove attach data from list */
  322.  Remove((struct Node *) tmpd->tmpd_Data);
  323.  
  324.  /* Free attach data */
  325.  FreeMemory(tmpd->tmpd_Data, sizeof(struct AttachData));
  326.  
  327.  /* Return 1 to indicate that the method is implemented */
  328.  return(1);
  329. }
  330.  
  331. /* Base class method: TMM_Edit */
  332. #undef  DEBUGFUNCTION
  333. #define DEBUGFUNCTION BaseClassEdit
  334. static ULONG BaseClassEdit(Class *cl, Object *obj, struct TMP_Edit *tmpe)
  335. {
  336.  struct BaseClassData *bcd  = TYPED_INST_DATA(cl, obj);
  337.  
  338.  BASE_LOG(LOG1(Arguments, "Group 0x%08lx", tmpe->tmpe_Group))
  339.  
  340.  /* Already editing? */
  341.  if (bcd->bcd_Active) {
  342.  
  343.   /* Yes, move window to front */
  344.   DoMethod(obj, MUIM_Window_ToFront);
  345.  
  346.   /* Activate window */
  347.   set(obj, MUIA_Window_Activate, TRUE);
  348.  
  349.  /* No, create Name area */
  350.  } else if (bcd->bcd_Active = HGroup,
  351.                                Child, Label2(TextName),
  352.                                Child, bcd->bcd_String =
  353.                                 TMString(bcd->bcd_Name, LENGTH_STRING,
  354.                                          HelpName),
  355.                               End) {
  356.   Object *UseButton;
  357.   Object *CancelButton;
  358.  
  359.   BASE_LOG(LOG1(Name Area, "0x%08lx", bcd->bcd_Active))
  360.  
  361.   /* Create ButtonArea */
  362.   if (bcd->bcd_Buttons = HGroup,
  363.                           Child, UseButton    = MakeButton(TextGlobalUse,
  364.                                                            HelpGlobalUse),
  365.                           Child, HSpace(0),
  366.                           Child, CancelButton = MakeButton(TextGlobalCancel,
  367.                                                            HelpGlobalCancel),
  368.                          End) {
  369.  
  370.    BASE_LOG(LOG1(Button Area, "0x%08lx", bcd->bcd_Buttons))
  371.  
  372.    /* Add objects to root group */
  373.    DoMethod(bcd->bcd_Root, OM_ADDMEMBER, bcd->bcd_Active);
  374.    if (bcd->bcd_Child = tmpe->tmpe_Group)
  375.     DoMethod(bcd->bcd_Root, OM_ADDMEMBER, bcd->bcd_Child);
  376.    DoMethod(bcd->bcd_Root, OM_ADDMEMBER, bcd->bcd_Buttons);
  377.  
  378.    /* Button actions                                           */
  379.    /* NOTE: The Method has to be pushed because button objects */
  380.    /*       are disposed during the execution of the method!   */
  381.    DoMethod(UseButton,    MUIM_Notify, MUIA_Pressed, FALSE,
  382.             MUIV_Notify_Application, 6, MUIM_Application_PushMethod,
  383.             bcd->bcd_List, 3, TMM_Update, obj, TMV_Finish_Use);
  384.    DoMethod(CancelButton, MUIM_Notify, MUIA_Pressed, FALSE,
  385.             MUIV_Notify_Application, 6, MUIM_Application_PushMethod,
  386.             bcd->bcd_List, 3, TMM_Update, obj, TMV_Finish_Cancel);
  387.  
  388.    /* String action (only if no child objects) */
  389.    if (bcd->bcd_Child == NULL)
  390.     DoMethod(bcd->bcd_String, MUIM_Notify,
  391.              MUIA_String_Acknowledge, MUIV_EveryTime,
  392.              MUIV_Notify_Application, 6, MUIM_Application_PushMethod,
  393.              bcd->bcd_List, 3, TMM_Update, obj, TMV_Finish_Use);
  394.  
  395.    /* Add object to application */
  396.    DoMethod(_app(bcd->bcd_List), OM_ADDMEMBER, obj);
  397.  
  398.    /* Position window and activate name string gadget */
  399.    SetAttrs(obj, MUIA_Window_LeftEdge,     MUIV_Window_LeftEdge_Moused,
  400.                  MUIA_Window_TopEdge,      MUIV_Window_TopEdge_Moused,
  401.                  MUIA_Window_ActiveObject, bcd->bcd_String,
  402.                  TAG_DONE);
  403.  
  404.    /* Open window */
  405.    SetAttrs(obj, MUIA_Window_Open, TRUE, TAG_DONE);
  406.  
  407.   } else {
  408.    /* Can't create button area, delete name area again */
  409.    MUI_DisposeObject(bcd->bcd_Active);
  410.    bcd->bcd_Active = NULL;
  411.   }
  412.  }
  413.  
  414.  BASE_LOG(LOG1(Result, "0x%08lx", bcd->bcd_Active))
  415.  
  416.  /* Return pointer to name area object to indicate success */
  417.  return((ULONG) bcd->bcd_Active);
  418. }
  419.  
  420. /* Base class method: TMM_WriteIFF */
  421. #undef  DEBUGFUNCTION
  422. #define DEBUGFUNCTION BaseClassWriteIFF
  423. static ULONG BaseClassWriteIFF(Class *cl, Object *obj,
  424.                                struct TMP_WriteIFF *tmpwi)
  425. {
  426.  BOOL rc;
  427.  
  428.  BASE_LOG(LOG1(Arguments, "IFFHandle 0x%08lx", tmpwi->tmpwi_IFFHandle))
  429.  
  430.  rc = WriteStringProperty(tmpwi->tmpwi_IFFHandle, ID_NAME,
  431.                           TYPED_INST_DATA(cl, obj)->bcd_Name);
  432.  
  433.  BASE_LOG(LOG1(Result, "%ld", rc))
  434.  
  435.  return(rc);
  436. }
  437.  
  438. /* Base class method: TMM_WBArg */
  439. #undef  DEBUGFUNCTION
  440. #define DEBUGFUNCTION BaseClassWBArg
  441. static ULONG BaseClassWBArg(Class *cl, Object *obj, struct TMP_WBArg *tmpwa)
  442. {
  443.  struct BaseClassData *bcd  = TYPED_INST_DATA(cl, obj);
  444.  char                 *name = tmpwa->tmpwa_Argument->wa_Name;
  445.  ULONG                 rc   = 0;
  446.  
  447.  BASE_LOG(LOG2(Name, "%s (0x%08lx)", name, name))
  448.  
  449.  /* Edit active and icon name valid? */
  450.  if (bcd->bcd_Active && name && (*name != '\0')) {
  451.  
  452.   BASE_LOG(LOG0(Edit active))
  453.  
  454.   /* Yes, set name string */
  455.   SetAttrs(bcd->bcd_String, MUIA_String_Contents, name, TAG_DONE);
  456.  
  457.   /* Set object name */
  458.   SetAttrs(obj, TMA_Name, name, TAG_DONE);
  459.  
  460.   /* Return pointer to ourself */
  461.   rc = (ULONG) obj;
  462.  }
  463.  
  464.  BASE_LOG(LOG1(Result, "0x%08lx", rc))
  465.  
  466.  return(rc);
  467. }
  468.  
  469. /* Base class method dispatcher */
  470. #undef  DEBUGFUNCTION
  471. #define DEBUGFUNCTION BaseClassDispatcher
  472. __geta4 static ULONG BaseClassDispatcher(__a0 Class *cl, __a2 Object *obj,
  473.                                          __a1 Msg msg)
  474. {
  475.  ULONG rc;
  476.  
  477.  BASE_LOG(LOG3(Arguments, "Class 0x%08lx Object 0x%08lx Msg 0x%08lx",
  478.                cl, obj, msg))
  479.  
  480.  switch(msg->MethodID) {
  481.   /* BOOPSI methods */
  482.   case OM_NEW:
  483.    rc = BaseClassNew(cl, obj, (struct opSet *) msg);
  484.    break;
  485.  
  486.   case OM_DISPOSE:
  487.    rc = BaseClassDispose(cl, obj, msg);
  488.    break;
  489.  
  490.   case OM_SET:
  491.    rc = BaseClassSet(cl, obj, (struct opSet *) msg);
  492.    break;
  493.  
  494.   case OM_GET:
  495.    rc = BaseClassGet(cl, obj, (struct opGet *) msg);
  496.    break;
  497.  
  498.   /* TM methods */
  499.   case TMM_Finish:
  500.    rc = BaseClassFinish(cl, obj, (struct TMP_Finish *) msg);
  501.    break;
  502.  
  503.   case TMM_Attach:
  504.    rc = BaseClassAttach(cl, obj, (struct TMP_Attach *) msg);
  505.    break;
  506.  
  507.   case TMM_Detach:
  508.    rc = BaseClassDetach(cl, obj, (struct TMP_Detach *) msg);
  509.    break;
  510.  
  511.   case TMM_Edit:
  512.    rc = BaseClassEdit(cl, obj, (struct TMP_Edit *) msg);
  513.    break;
  514.  
  515.   case TMM_WriteIFF:
  516.    rc = BaseClassWriteIFF(cl, obj, (struct TMP_WriteIFF *) msg);
  517.    break;
  518.  
  519.   case TMM_WBArg:
  520.    rc = BaseClassWBArg(cl, obj, (struct TMP_WBArg *) msg);
  521.    break;
  522.  
  523.   /* Unknown method -> delegate to SuperClass */
  524.   default:
  525.    rc = DoSuperMethodA(cl, obj, msg);
  526.    break;
  527.  }
  528.  
  529.  return(rc);
  530. }
  531.  
  532. /* Create Base class */
  533. #undef  DEBUGFUNCTION
  534. #define DEBUGFUNCTION CreateBaseClass
  535. struct MUI_CustomClass *CreateBaseClass(void)
  536. {
  537.  struct MUI_CustomClass *rc;
  538.  
  539.  /* Create class */
  540.  if (rc = MUI_CreateCustomClass(NULL, MUIC_Window, NULL,
  541.                                 sizeof(struct BaseClassData),
  542.                                 BaseClassDispatcher)) {
  543.  
  544.   /* Localize strings */
  545.   TextName   = TranslateString(LOCALE_TEXT_BASE_NAME_STR,
  546.                                LOCALE_TEXT_BASE_NAME);
  547.   HelpName   = TranslateString(LOCALE_HELP_BASE_NAME_STR,
  548.                                LOCALE_HELP_BASE_NAME);
  549.  }
  550.  
  551.  BASE_LOG(LOG1(Result, "0x%08lx", rc))
  552.  
  553.  return(rc);
  554. }
  555.